package core;

import infrastructure.exceptions.PrivilidgesException;
import infrastructure.exceptions.ServerFataError;
import infrastructure.exceptions.operations.OperationException;

import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;


import dal.JPAAgent;
import dal.Pet;
import dal.Pet_type;
import dal.User;
import remote.SerializableIterator;
import remote.Session;
import server.IAdminInterface;
import server.querry.Condition;

public class AdminInterface extends ServerSession implements IAdminInterface{
 

	private static final long serialVersionUID = -3671655399627376546L;

	public AdminInterface(Session userSession){
		super(userSession);
	}
	
	
	public void addUser(String username, String password,Boolean isAdministrator) throws OperationException {
		checkAccess();
		
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();
			EntityTransaction transaction = entityManager.getTransaction();			
						
			transaction.begin();
			User newUSer = new User(username,password,isAdministrator);
			entityManager.persist(newUSer);
			transaction.commit();
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"addUser", "Could add user'" ,ex);
			throw new OperationException("Adding user failed" + ex.getMessage());
		}
		
		
	}

	public Iterator<User> getAllUsers() {
		checkAccess();
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();						
			Query getAllUsersQerry = entityManager.createQuery("SELECT x from USERS x");						
			List<User>  usersList = getAllUsersQerry.getResultList();
			return new SerializableIterator(usersList);
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"getAllUsers", "Could get all users'" ,ex);
			return new SerializableIterator(Collections.EMPTY_LIST);
		}
	}

	public void removeUser(String username) throws OperationException {
		
		checkAccess();
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();
			entityManager.getTransaction().begin();
			Query getAllUsersQerry = entityManager.createQuery("SELECT x from USERS x WHERE x.username like '" + username + "'");						
			List<User>  usertoRemove =  getAllUsersQerry.getResultList();
			
			// check if we get any
			if (!usertoRemove.isEmpty()){
				if (usertoRemove.size() == 1){
					Logger.getLogger(this.getClass().getName()).logp(Level.INFO, this.getClass().getName(), 
							"removeUser", "removing user User '" + username + "'");
					entityManager.remove(usertoRemove.get(0));
				}else{
					Logger.getLogger(this.getClass().getName()).logp(Level.SEVERE, this.getClass().getName(), 
							"removeUser", "Returned multiple results .. but only one should be returned .. db bug'");	
				}
			}else{
				Logger.getLogger(this.getClass().getName()).logp(Level.INFO, this.getClass().getName(), 
						"removeUser", "User '" + username + "' does not exists .. nothing to remove");	
			}
			
			
			entityManager.getTransaction().commit();
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"removeUser", "Remove user failed'" ,ex);			
		}
	}


	public void addPetType(Pet_type typeToAdd) throws OperationException {
		
		Logger.getLogger(this.getClass().getName()).logp(Level.INFO, this.getClass().getName(), 
				"addPetType", "Adding pet type '" + typeToAdd + "'");
		
		checkAccess();
		
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();
			EntityTransaction transaction = entityManager.getTransaction();			
						
			transaction.begin();			
			entityManager.persist(typeToAdd);
			transaction.commit();
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"addPetType", "Could add pet type'" ,ex);
			throw new OperationException("Adding pet type failed" + ex.getMessage());
		}
	}


	public void removePetType(String typeToRemove) {		
		
		Logger.getLogger(this.getClass().getName()).logp(Level.SEVERE, this.getClass().getName(), 
				"removePetType", "Remove pet type is called for type '" + typeToRemove + "' user '" + this.userSession.getUser().getUsername() + "'");	
		
		checkAccess();
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();
			entityManager.getTransaction().begin();
			Query getAllUsersQerry = entityManager.createQuery("SELECT x from pet_types x WHERE x.type_name like '" + 
					typeToRemove + "'");						
			List<Pet_type>  petTypesToRemove =  getAllUsersQerry.getResultList();
			
			// check if we get any
			if (!petTypesToRemove.isEmpty()){
				if (petTypesToRemove.size() == 1){
					Logger.getLogger(this.getClass().getName()).logp(Level.INFO, this.getClass().getName(), 
							"removePetType", "removing pet type  '" + typeToRemove + "'");
					entityManager.remove(petTypesToRemove.get(0));
				}else{
					Logger.getLogger(this.getClass().getName()).logp(Level.SEVERE, this.getClass().getName(), 
							"removePetType", "Returned multiple results .. but only one should be returned .. db bug'");	
				}
			}else{
				Logger.getLogger(this.getClass().getName()).logp(Level.INFO, this.getClass().getName(), 
						"removePetType", "User '" + typeToRemove + "' does not exists .. nothing to remove");	
			}
			
			
			entityManager.getTransaction().commit();
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"removePetType", "Remove user failed'" ,ex);			
		}
	}
	
	
}
